//////////////////////////////////////////////////////////////////////////
// $Id: Context.cpp,v 1.1 2009/04/03 12:46:11 sunjun Exp $
//////////////////////////////////////////////////////////////////////////

#include "Local.h"

//////////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////////

NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////	

	Context::Context() : mHandle(NULL)
	{
		mCRT = NULL;
		mDRT = NULL;
	}

	Context::~Context() 
	{
		if((IDirect3DSurface9*)mCRT){((IDirect3DSurface9*)mCRT)->Release(); mCRT = NULL;}
		if((IDirect3DSurface9*)mDRT){((IDirect3DSurface9*)mDRT)->Release(); mDRT = NULL;}
		if((IDirect3DDevice9*)mHandle){((IDirect3DDevice9*)mHandle)->Release(); mHandle = NULL;}
	}

	//////////////////////////////////////////////////////////////////////////

	/*
	====================
	handle
	====================
	*/
	INLINE HANDLE Context::handle() const
	{
		return mHandle;
	}

	/*
	====================
	bind
	====================
	*/
	INLINE VOID Context::bind( HWND wnd )
	{
		HRESULT hr;

		if((IDirect3DSurface9*)mCRT){((IDirect3DSurface9*)mCRT)->Release(); mCRT = NULL;}
		if((IDirect3DSurface9*)mDRT){((IDirect3DSurface9*)mDRT)->Release(); mDRT = NULL;}		
		if((IDirect3DDevice9*)mHandle){((IDirect3DDevice9*)mHandle)->Release(); mHandle = NULL;}

		if( wnd == NULL ) return;

		// Get the current desktop format
		D3DDISPLAYMODE dispmode;
		hr = gD3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispmode);
		if (FAILED(hr)) MAssert(VA("Context::bind : GetAdapterDisplayMode failed %s", DXGetErrorDescription(hr)));

		// create d3d9 device
		D3DPRESENT_PARAMETERS d3dpp;
		memset(&d3dpp, 0, sizeof(d3dpp));
		d3dpp.BackBufferWidth = 0;
		d3dpp.BackBufferHeight = 0;
		d3dpp.BackBufferFormat = dispmode.Format;
		d3dpp.BackBufferCount = 1;
		d3dpp.EnableAutoDepthStencil= TRUE;
		d3dpp.AutoDepthStencilFormat= D3DFMT_D24S8;
		d3dpp.Flags = 0;
		d3dpp.Windowed = TRUE;
		d3dpp.hDeviceWindow = wnd;
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
		DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE|D3DCREATE_MULTITHREADED;
		IDirect3DDevice9 * d3d9Device = NULL;
		hr = gD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, behavior_flags, &d3dpp, &d3d9Device);
		if(FAILED(hr))  MAssert(VA("Context::bind : CreateDevice failed %s", DXGetErrorDescription(hr)));
		mHandle = d3d9Device;

		// get the main framebuffer and depth buffer surfaces
		IDirect3DSurface9*d3d9Surface = NULL;
		hr = d3d9Device->GetRenderTarget(0,&d3d9Surface);
		if(FAILED(hr))  MAssert(VA("Context::bind : GetRenderTarget failed %s", DXGetErrorDescription(hr)));
		mCRT = d3d9Surface;
		hr = d3d9Device->GetDepthStencilSurface(&d3d9Surface);
		if(FAILED(hr))  MAssert(VA("Context::bind : GetDepthStencilSurface failed %s", DXGetErrorDescription(hr)));
		mDRT = d3d9Surface;
	}

	/*
	====================
	exec
	====================
	*/
	INLINE VOID Context::exec( const Operation * op )
	{
		(*((Operation*)op))(this);
	}

//////////////////////////////////////////////////////////////////////////

NAMESPACE_END

//////////////////////////////////////////////////////////////////////////
